#include <boost/bind.hpp>

#include <kugou/server/http/HTTPServer.h>

namespace kugou
{
namespace server
{
namespace http
{

HTTPServer::HTTPServer(const std::string& address, const std::string& port, const std::string& doc_root)
    : m_ioService()
    , m_acceptorPtr(new boost::asio::ip::tcp::acceptor(m_ioService))
    , m_connectionManager()
    , m_newConnection(new HTTPConnection(m_ioService, m_connectionManager, m_requestHandler))
    , m_requestHandler(doc_root)
    , m_docRoot(doc_root)
{
    //Open the acceptor with the option to reuse the address.
    boost::asio::ip::tcp::resolver resolver(m_ioService);
    boost::asio::ip::tcp::resolver::query query(address,port);
    boost::asio::ip::tcp::endpoint endpoint = *(resolver.resolve(query));

    m_acceptorPtr->open(endpoint.protocol());
    m_acceptorPtr->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
    m_acceptorPtr->bind(endpoint);
    m_acceptorPtr->listen();
    m_acceptorPtr->async_accept(m_newConnection->socket(),
      boost::bind(&HTTPServer::handleAccept, this,
        boost::asio::placeholders::error));
}

void HTTPServer::run()
{
    m_ioService.run();
}

void HTTPServer::stop()
{
    m_ioService.post(boost::bind(&HTTPServer::handleStop, this));
}

void HTTPServer::handleAccept(const boost::system::error_code& e)
{
    if(!e)
    {
        m_connectionManager.start(m_newConnection);
        m_newConnection.reset(new HTTPConnection(m_ioService, m_connectionManager, m_requestHandler));
        m_acceptorPtr->async_accept(m_newConnection->socket(),
          boost::bind(&HTTPServer::handleAccept, this,
            boost::asio::placeholders::error));
    }
}

void HTTPServer::handleStop()
{
    // The server is stopped by cancelling all outstanding asynchronous
    // operations. Once all operations have finished the io_service::run() call
    // will exit.
    m_acceptorPtr->close();
    m_connectionManager.stopAll();
}

} // http    
} // server
} // kugou
